﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Wf5.Engine.Common;
using Wf5.Engine.Utility;
using FCDB.Entity;
using FCDB.Repository;
using FCDB.Entity.EntityEx;

namespace Wf5.Engine.Business
{
    /// <summary>
    /// 任务管理类：包括任务及任务视图对象
    /// </summary>
    public class TaskManager
    { 
        #region TaskManager 属性列表
        private WfTasksRepository _taskRepository;
        private WfTasksRepository TaskRepository
        {
            get
            {
                if (_taskRepository == null)
                {
                    _taskRepository = new WfTasksRepository();
                }
                return _taskRepository;
            }
        }

        private WfActivityInstanceTasksRepository _taskViewRepository;
        private WfActivityInstanceTasksRepository TaskViewRepository
        {
            get
            {
                if (_taskViewRepository == null)
                {
                    _taskViewRepository = new  WfActivityInstanceTasksRepository();
                }
                return _taskViewRepository;
            }
        }

        #endregion

        #region TaskManager 任务分配视图
        public WfActivityInstanceTasksEx GetTaskView(long taskID)
        {
            return TaskViewRepository.Get<WfActivityInstanceTasksEx>(taskID);
        }

        public WfTasks GetTask(long taskID)
        {
            return TaskRepository.Get<WfTasks>(taskID);
        }


        #region TaskManager 获取当前用户的办理任务
        /// <summary>
        /// 获取当前用户运行中的任务
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        internal IEnumerable<WfActivityInstanceTasksEx> GetRunningTasks(TaskQueryEntity query, out int allRowsCount)
        {
            return GetTasksPaged(query, 2, out allRowsCount);
        }
         /// <summary>
        /// 获取当前用户运行中的下个节点的任务
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        internal IEnumerable<WfActivityInstanceTasksEx> GetRunningTasksByCreateUser(TaskQueryEntity query, out int allRowsCount)
        {
            return GetTasksByCreateUserPaged(query, 2, out allRowsCount);
        }
        /// <summary>
        /// 获取当前用户待办的任务
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        internal IEnumerable<WfActivityInstanceTasksEx> GetReadyTasks(TaskQueryEntity query, out int allRowsCount)
        {
            return GetTasksPaged(query, 1, out allRowsCount);
        } 

        /// <summary>
        /// 获取任务（分页）
        /// </summary>
        /// <param name="query"></param>
        /// <param name="activityState"></param>
        /// <returns></returns>
        private IEnumerable<WfActivityInstanceTasksEx> GetTasksPaged(TaskQueryEntity query, int activityState, out int allRowsCount)
        {
            //processState:2 -running 流程处于运行状态
            //activityType:4 -表示“任务”类型的节点
            //activityState: 1-ready（准备）, 2-running（）运行；
            var list=  TaskViewRepository.GetTasksPaged(query.AppInstanceID, query.ProcessGUID, query.UserID,
                activityState,query.PageIndex, query.PageSize,out  allRowsCount);
            
            return list;
        }  
        /// <summary>
        /// 获取任务（分页）
        /// </summary>
        /// <param name="query"></param>
        /// <param name="activityState"></param>
        /// <returns></returns>
        private IEnumerable<WfActivityInstanceTasksEx> GetTasksByCreateUserPaged(TaskQueryEntity query, int activityState, out int allRowsCount)
        {
            //processState:2 -running 流程处于运行状态
            //activityType:4 -表示“任务”类型的节点
            //activityState: 1-ready（准备）, 2-running（）运行；
            var list = TaskViewRepository.GetTasksByCreateUserPaged(query.AppInstanceID, query.ProcessGUID, query.UserID,
                activityState,query.PageIndex, query.PageSize,out  allRowsCount);
            
            return list;
        }
        #region GetTaskOfMine 
        internal IEnumerable<WfActivityInstanceTasksEx> GetTaskOfMine(WfAppRunner runner )
        {
            return GetTaskOfMine(runner.AppInstanceID, runner.ProcessGUID, runner.UserID);
        } 
        /// <summary>
        /// 根据应用实例、流程GUID，办理用户Id获取任务列表
        /// </summary>
        /// <param name="appInstanceID"></param>
        /// <param name="processGUID"></param>
        /// <param name="userID"></param>  
        /// <returns></returns>
        internal IEnumerable<WfActivityInstanceTasksEx> GetTaskOfMine(long appInstanceID, Guid processGUID, Guid userID)
        {
            //processState:2 -running 流程处于运行状态
            //activityType:4 -表示“任务”类型的节点
            //activityState: 1-ready（准备）, 2-running（）运行；
//            string whereSql = @"WHERE AppInstanceID=@appInstanceID AND ProcessGUID=@processGUID AND AssignedToUserID=@userID 
//                                AND ProcessState=2 AND ActivityType=4 AND (ActivityState=1 OR ActivityState=2) 
//                           ORDER BY TASKID DESC";
            return TaskViewRepository.GetTaskOfMine(appInstanceID, processGUID, userID); 
            
        }
        /// <summary>
        /// 根据应用实例、流程GUID，办理用户或者创建者Id获取任务列表
        /// </summary>
        /// <param name="appInstanceID"></param>
        /// <param name="processGUID"></param>
        /// <param name="userID"></param>  
        /// <returns></returns>
        internal IEnumerable<WfActivityInstanceTasksEx> GetTaskOfForProcessSendBack(long appInstanceID, Guid processGUID, Guid userID)
        {
            //processState:2 -running 流程处于运行状态
            //activityType:4 -表示“任务”类型的节点
            //activityState: 1-ready（准备）, 2-running（）运行；
            //            string whereSql = @"WHERE AppInstanceID=@appInstanceID AND ProcessGUID=@processGUID AND AssignedToUserID=@userID 
            //                                AND ProcessState=2 AND ActivityType=4 AND (ActivityState=1 OR ActivityState=2) 
            //                           ORDER BY TASKID DESC";
            return TaskViewRepository.GetTaskOfMineForProcessSendBack(appInstanceID, processGUID, userID);

        }
#endregion 
        /// <summary>
        /// 获取登录用户的待办任务（某个应用实例下的待办任务，有唯一性。）
        /// </summary>
        /// <param name="appInstanceID"></param>
        /// <param name="processGUID"></param>
        /// <param name="userID"></param>
        /// <param name="session"></param>
        /// <returns></returns>
        internal WfActivityInstanceTasksEx GetReadyTaskOfMine(long appInstanceID, Guid processGUID, Guid userID)
        {

            var list = TaskViewRepository.GetReadyTaskOfMine(appInstanceID, processGUID, userID);
            return list;
        }

        /// <summary>
        /// 判断活动实例是否是某个用户的任务
        /// </summary>
        /// <param name="activityInstanceID"></param>
        /// <param name="userID"></param>
        /// <param name="session"></param>
        /// <returns></returns>
        internal bool IsMine(long activityInstanceID, Guid userID)
        {
            return TaskRepository.IsMine(activityInstanceID, userID);
          
        }

        public IEnumerable<WfActivityInstanceTasksEx> GetReadyTaskOfApp(WfAppRunner runner)
        {
            //processState:2 -running 流程处于运行状态
            //activityType:4 -表示“任务”类型的节点
            //activityState: 1-ready（准备）
//            string whereSql = @"WHERE AppInstanceID=@appInstanceID 
//                                    AND ProcessGUID=@processGUID 
//                                    AND ProcessState=2 AND ActivityType=4 AND ActivityState=1";

            var list = TaskViewRepository.GetReadyTaskOfApp(runner.AppInstanceID, runner.ProcessGUID);
            return list;
        }
        #endregion


        /// <summary>
        /// 获取流程实例下的任务数据
        /// </summary>
        /// <param name="appInstanceID">应用ID</param>
        /// <param name="ProcessInstanceID">流程实例ID</param>
        /// <returns>任务列表数据</returns>
        internal IEnumerable<WfActivityInstanceTasksEx> GetProcessTasks(int appInstanceID,
            int processInstanceID)
        {
            string whereSql = @"WHERE ApplicationInstaceID=@appInstanceID 
                            AND ProcessInstanceID=@processInstanceID";
            IList<WfActivityInstanceTasksEx> list = TaskViewRepository.GetProcessTasks(  appInstanceID,  processInstanceID );
            return list;

        }

        internal IEnumerable<WfActivityInstanceTasksEx> GetProcessTasksWithState(int appInstanceID,
            int processInstanceID,
            NodeStateEnum state)
        {
//            string whereSql = @"WHERE ApplicationInstaceID=@appInstanceID 
//                            AND ProcessInstanceID=@processInstanceID 
//                            AND State=@state";
            var list = TaskViewRepository.GetProcessTasksWithState( appInstanceID, processInstanceID, (short) state) ;
            return list;
        }

       
        #endregion

        #region TaskManager 任务数据基本操作
        /// <summary>
        /// 插入任务数据
        /// </summary>
        /// <param name="entity">任务实体</param>
        /// <param name="wfLinqDataContext">linq上下文</param>
        internal void Insert(WfTasks entity )
        {
           
              TaskRepository.Add(entity);
            Debug.WriteLine(string.Format("task instance inserted, time:{0}", System.DateTime.Now.ToString()));
        }

        /// <summary>
        /// 插入任务数据
        /// </summary>
        /// <param name="activityInstance"></param>
        /// <param name="performers"></param>
        /// <param name="wfLinqDataContext"></param>
        internal void Insert(WfActivityInstance activityInstance,
            PerformerList performers, 
            WfLogonUser logonUser)
        {
            foreach (Performer performer in performers)
            {
                WfTasks entity = new WfTasks();
                entity.ID = IDCreateLogic.GenerateID("WfTasks", "任务ID");
                entity.AppName = activityInstance.AppName;
                entity.AppInstanceID = activityInstance.AppInstanceID;
                entity.ActivityInstanceID = activityInstance.ID;
                entity.ProcessInstanceID = activityInstance.ProcessInstanceID;
                entity.ActivityGUID = activityInstance.ActivityGUID;
                entity.ActivityName = activityInstance.ActivityName;
                entity.ProcessGUID = activityInstance.ProcessGUID;
                entity.TaskType = (short)TaskTypeEnum.Manual;
                entity.AssignedToUserID = performer.UserID;
                entity.AssignedToUserName = performer.UserName;
                entity.TaskState = 1; //1-待办状态
                entity.CreatedByUserID = logonUser.UserID;
                entity.CreatedByUserName = logonUser.UserName;
                entity.CreatedDateTime = System.DateTime.Now;
                entity.RecordStatusInvalid = 0;
                //插入任务数据
                Insert(entity);
            }
        }

        /// <summary>
        /// 更新任务数据
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="wfLinqDataContext"></param>
        internal void Update(WfTasks entity )
        {
            TaskRepository.Update(entity);
        }

        internal void Read(WfAppRunner runner)
        {
            //读取登录用户的待办任务 
            var taskOfReady = GetReadyTaskOfMine(runner.AppInstanceID, runner.ProcessGUID, runner.UserID);
            if (taskOfReady == null)
            {
                return;
                //throw new WorkflowException("当前用户没有待办任务记录，无法进行设置在办的操作！");
            }

            //将待办任务设置为运行状态，表示接受任务。
            Read(taskOfReady.TaskID, runner.UserID, runner.UserName);
        }

        /// <summary>
        /// 读取任务，设置任务为已读状态
        /// </summary>
        /// <param name="taskID"></param>
        /// <param name="userID"></param>
        /// <param name="userName"></param>
        internal void Read(long taskID,
            Guid userID,
            string userName)
        {
           
            try
            {
                //置任务为处理状态
                var task = GetTask(taskID);
                var logonUser = new WfLogonUser(userID, userName);
                SetTaskState(task, logonUser, TaskStateEnum.Handling);

                //置活动为运行状态
                (new ActivityInstanceManager()).Read(task.ActivityInstanceID, logonUser);

               
            }
            catch (System.Exception e)
            {
              
                throw new WorkflowException(string.Format("阅读待办任务时出错！，详细错误：{0}", e.Message), e);
            }
          
        }

        /// <summary>
        /// 设置任务状态
        /// </summary>
        /// <param name="task"></param>
        /// <param name="logonUser"></param>
        /// <param name="taskState"></param>
        /// <param name="session"></param>
        private void SetTaskState(WfTasks task,
            WfLogonUser logonUser,
            TaskStateEnum taskState)
        {
            task.TaskState = (short)taskState;
            task.LastUpdatedByUserID = logonUser.UserID;
            task.LastUpdatedByUserName = logonUser.UserName;
            task.LastUpdatedDateTime = System.DateTime.Now;
            Update(task);
        }



        /// <summary>
        /// 设置任务完成
        /// </summary>
        /// <param name="taskID">任务ID</param>
        /// <param name="currentLogonUser"></param>
        /// <param name="wfLinqDataContext"></param>
        public void Complete(long taskID,
            WfLogonUser currentLogonUser
           )
        {
            WfTasks task = TaskRepository.Get<WfTasks>(taskID);
            task.TaskState = (byte)TaskStateEnum.Completed;
            task.EndedDateTime = DateTime.Now;
            task.EndedByUserID = currentLogonUser.UserID;
            task.EndedByUserName = currentLogonUser.UserName;
            Update(task);
        }

        /// <summary>
        /// 任务删除
        /// </summary>
        /// <param name="taskID">任务ID</param>
        internal void Delete(long taskID)
        {
            try
            {
                TaskRepository.Delete<WfTasks>(taskID);
                
            }
            catch (System.Exception)
            {
                throw;
            }
           
        }
        #endregion

        #region TaskManager 获取任务下一步列表方法，供应用界面显示
       

        /// <summary>
        /// 获取当前办理任务的下一步
        /// </summary>
        /// <param name="runner"></param>
        /// <param name="condition"></param>
        /// <param name="session"></param>
        /// <returns></returns>
        internal IList<NodeView> GetNextActivityTree(WfAppRunner runner,
            IDictionary<string, string> condition)
        {
            var processModel = new ProcessModel(runner.ProcessGUID);
            var taskList = GetTaskOfMine(runner).ToList();
            if (taskList == null || taskList.Count == 0)
            {
                throw new WorkflowException("没有当前你正在办理的任务，流程无法读取下一步节点！");
            }
            else if (taskList.Count > 1)
            {
                throw new WorkflowException(string.Format("当前应用ID的办理任务数目要唯一，不是正确的任务数目！错误数目：{0}", taskList.Count));
            }

            var task = taskList[0];
            var nextSteps = processModel.GetNextActivityTree(task.ActivityGUID, condition);
            return nextSteps;
        }
        #endregion
    }
}
